package com.gitee.cirnochat.chatai.service.impl;


import com.gitee.cirnochat.chatai.client.DeepDuckChatClient;
import com.gitee.cirnochat.chatai.model.dto.lke.LkeAskRequest;
import com.gitee.cirnochat.chatai.model.vo.req.aimsg.AiChatMessageDTO;
import com.gitee.cirnochat.chatai.model.vo.req.aisession.AISessionCreateDTO;
import com.gitee.cirnochat.chatai.model.vo.req.aisession.AISessionUpdateDTO;
import com.gitee.cirnochat.chatai.model.vo.req.aisummary.AISummaryTextDTO;
import com.gitee.cirnochat.chatai.model.entity.AiChatMessage;
import com.gitee.cirnochat.chatai.model.entity.AiChatSession;
import com.gitee.cirnochat.chatai.model.enums.aimodel.AIModelType;
import com.gitee.cirnochat.chatai.model.vo.resp.AIChatSessionVo;
import com.gitee.cirnochat.chatai.model.vo.resp.AiChatSessionMessageVo;
import com.gitee.cirnochat.chatai.service.AiChatService;
import com.gitee.cirnochat.chatai.service.AiChatMessageService;
import com.gitee.cirnochat.chatai.service.AiChatSessionService;
import com.gitee.cirnochat.chatai.service.AiSummaryService;
import com.gitee.cirnochat.common.model.vo.resp.PageVo;
import com.gitee.cirnochat.common.model.vo.resp.StreamData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class AiChatServiceImpl implements AiChatService {
    private final AiChatSessionService aiChatSessionService;
    private final AiChatMessageService aiChatMessageService;
    private final AiSummaryService aiSummaryService;
    private final DeepDuckChatClient chatClient;

    //region 会话相关

    @Override
    public AIChatSessionVo createSession(AISessionCreateDTO sessionCreateDTO, Long userId) {
        AiChatSession aiChatSession = new AiChatSession(sessionCreateDTO, userId, true);
        aiChatSessionService.save(aiChatSession);
        return new AIChatSessionVo(aiChatSession);
    }

    @Override
    public PageVo<AIChatSessionVo> getSessionList(String searchName, int page, int size, Long userId) {
        return aiChatSessionService.pageSessionList(searchName, page, size, userId);
    }

    @Override
    public void deleteSession(Long sessionId, Long userId) {
        aiChatSessionService.removeSessionById(sessionId, userId);
        aiChatMessageService.removeMessagesBySessionIdAsync(sessionId);
    }

    @Override
    public AIChatSessionVo updateSession(AISessionUpdateDTO sessionUpdateDTO, Long userId) {
        AiChatSession aiChatSession = aiChatSessionService.updateSessionById(sessionUpdateDTO, userId);
        return new AIChatSessionVo(aiChatSession);
    }

    // endregion

    //region 消息相关
    @Override
    public List<AiChatSessionMessageVo> getMessagesBySessionId(Long sessionId, Long userId) {
        List<AiChatMessage> messages = aiChatMessageService.getMessagesBySessionId(sessionId, userId);
        return messages.isEmpty() ? List.of() : messages.stream().map(AiChatSessionMessageVo::new).toList();
    }


    @Override
    public void completeOutput(SseEmitter sseEmitter, AiChatMessageDTO dto, Long userId) {
        Flux<StreamData<?>> streamDataFlux = chatClient.stream(new LkeAskRequest(
                        dto.getSessionId(),
                        userId,
                        dto.getContent(),
                        dto.getModel(),
                        dto.getSearchNetwork() ? "enable" : "disable"
                ))
                .delayElements(Duration.ofMillis(50)) // 非阻塞延迟
                .subscribeOn(Schedulers.boundedElastic());
        streamDataFlux.subscribe(
                data -> {
                    try {
                        sseEmitter.send(data);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                },
                error -> {
                    log.error("Error during streaming: ", error);
                    sseEmitter.completeWithError(error);
                },
                sseEmitter::complete
        );

    }


    @Override
    public String getSummaryFromText(AISummaryTextDTO dto) {
        return aiSummaryService.getSummaryFromText(dto.getContent());
    }

    @Override
    public String getSummaryFromText(String content) {
        return aiSummaryService.getSummaryFromText(content);
    }

    //endregion

    @Override
    public List<String> getSupportModels() {
        return Arrays.stream(AIModelType.values()).map(AIModelType::getValue).toList();
    }
}
